
import os
import json

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *


context = None
def init(context_):
    global context
    context = context_

class ActionNewNode:
    def __init__(self, kind, node):
        self._kind = kind
        self._node = node
    def __del__(self):
        pass
    def on_add_testcasesq(self, value):
        global context
        # 测试用例序列绑定测试函数
        # 选择绑定的函数
        procedures = self._node.get_allchildren_by_kind('Procedure')
        procedures_names = [procedure.get_name()+"["+procedure.get_prop('usr')+"]" for procedure in procedures]
        procedures_map = {}
        for i in range(0, len(procedures)):
            procedures_map[procedures_names[i]] = procedures[i]

        item, okPressed = QInputDialog.getItem(None, "选择测试函数","函数:", procedures_names, 0, False)
        if okPressed and item:
            # 创建测试用例序列
            text, ok = QInputDialog().getText(None, "输入测试序列名称", "name:", QLineEdit.Normal)
            if ok and text:
                data_service = context.find_service("DataService")
                new_node = data_service.create_node("TestCaseSequence", text)
                new_node.set_prop("usr", procedures_map[item].get_prop('usr'))
                self._node.add_child(new_node)

    def on_stub_calls(self, value):
        global context
        # 测试用例序列绑定测试函数
        # 选择绑定的函数
        data_service = context.find_service("DataService")
        root = data_service.root_node()

        procedures = root.get_allchildren_by_kind('Procedure')
        usr2procedure = {}
        for pro in procedures:
            usr2procedure[pro.get_prop('usr')] = pro

        usr = self._node.get_prop('usr')
        pro_f = usr2procedure[usr]

        calls = pro_f.get_prop('calls')
        calls = json.loads(calls)
        calls = [call['usr'] for call in calls]

        
        procedures = [ proce for proce in procedures if proce.get_prop('usr') in calls ]

        procedures_names = [procedure.get_name()+"["+procedure.get_prop('usr')+"]" for procedure in procedures]
        procedures_map = {}
        for i in range(0, len(procedures)):
            procedures_map[procedures_names[i]] = procedures[i]

        item, okPressed = QInputDialog.getItem(None, "选择待打桩函数","函数:", procedures_names, 0, False)
        if okPressed and item:
            # 输入打桩函数实现
            text, ok = QInputDialog().getMultiLineText(None, "插桩函数实现", "实现:", "")
            if ok and text:
                proc_choose = procedures_map[item]
                self._node.set_prop(proc_choose.get_prop('usr')+'[call]', text)

    def on_add_testcase(self, value):
        global context

        #  

        # 通过文件对话框选择文件
        fileName_choose, filetype = QFileDialog.getOpenFileName(None,  
            "选取文件",  
            "", # 起始路径 
            "All Files (*);;C Files (*.c)")   
        print(fileName_choose, filetype)
        if fileName_choose=="":
            return 

        # 文件名称
        file_name = os.path.basename(fileName_choose)

        # 创建对应的文件对象
        print("on_new_node")

        data_service = context.find_service("DataService")
        new_node = data_service.create_node("File", file_name)
        new_node.set_prop("path", fileName_choose)
        self._node.add_child(new_node)


class DataExploreMenu:
    def __init__(self):
        self.menus = []
    def priorty(self):
        return 1000
    def add_menu(self, menu, nodes):
        self.menus = []
    
        kind = ""
        if len(nodes) == 1:
            node = nodes[0]
            kind = node.get_kind()

            if kind == "Project":
                # 测试序列
                action = menu.addAction("新建测试用例序列")

                obj = ActionNewNode(kind, node)
                self.menus.append(obj)
                action.triggered.connect(obj.on_add_testcasesq)
            elif kind == 'TestCase':
                # 打桩函数
                action = menu.addAction("调用函数打桩")

                obj = ActionNewNode(kind, node)
                self.menus.append(obj)
                action.triggered.connect(obj.on_stub_calls)
            '''
            elif kind == "TestCaseSequence":
                # 测试用例
                action = menu.addAction("新建测试用例")

                obj = ActionNewNode(kind, node)
                self.menus.append(obj)
                action.triggered.connect(obj.on_add_testcase)
            '''
        

def onNewNode(name, parent, node):
    global context

    if node.get_kind() == "TestCase":
        # 获取父亲节点
        #parent = node.parent()
        # 获取父节点usr属性
        usr = parent.get_prop('usr')
        node.set_prop('usr', usr)

        # 设置测试用例输入输出信息
        data_service = context.find_service("DataService")
        root = data_service.root_node()
        procedures = root.get_allchildren_by_kind('Procedure')
        
        usr2procedure = {}
        for procedure in procedures:
            usr2procedure[procedure.get_prop('usr')] = procedure

        if usr in usr2procedure:
            # 找到匹配函数
            procedure = usr2procedure[usr]

            in_vars = procedure.get_prop('inputs')
            out_vars = procedure.get_prop('outputs')

            in_vars = json.loads(in_vars)
            out_vars = json.loads(out_vars)

            for v in in_vars:
                node.set_prop(v['usr']+"[in]", "")
            for v in out_vars:
                node.set_prop(v['usr']+"[out]", "")

        
            # 调用函数标记
            calls = procedure.get_prop('calls')
            calls = json.loads(calls)

            for call in calls:
                if call['usr'] in usr2procedure:
                    if usr2procedure[call['usr']].get_prop('define') == 'true':
                        node.set_prop(call['usr']+"[call]", 'True')
                    else:
                        node.set_prop(call['usr']+"[call]", 'False')
                else:
                    node.set_prop(call['usr']+"[call]", 'False')

config = {
    'pluginid': 'UnitTest::UI::NewTestCase',
    "extensions" : [
        {
            "name": "PL::DataExplore::Menu",
            "id": "PL::DataExplore::Menu::UT::TestCase",
            "impl": DataExploreMenu()
        }
    ],
    "subscribes" : [
        {
            "name": 'event::DataNode::Modify::AddChild',
            "define": onNewNode
        }
    ]
}